#![allow(dead_code)]

use reqwest::{self, Client, Proxy, RequestBuilder, Response, StatusCode, Method};
use std::time::Duration;
use serde::{Serialize};
use std::collections::HashMap;
use thiserror::Error;
use serde::de::DeserializeOwned;
use crate::utils::ajax_result::AjaxResult;
use crate::utils::http_auth_manage::{get_token, set_auth_info};

/// 自定义错误类型
#[derive(Debug, Error)]
pub enum HttpAppError {
    #[error("Reqwest error: {0}")]
    Reqwest(#[from] reqwest::Error),

    #[error("HTTP status error: {0} - {1}")]
    Status(StatusCode, String),

    #[error("Custom error ({0}): {1}")]
    Custom(i32, String),
}

// 实现 From<String> trait
impl From<String> for HttpAppError {
    fn from(s: String) -> Self {
        HttpAppError::Custom {
            0: -1,
            1: s,
        }
    }
}


/// 拦截器上下文
#[derive(Debug, Default, Clone)]
pub struct HttpAppContext {
    pub skip_token: bool,
    pub headers: HashMap<String, String>,
    // 新增：cookies 为 Option<String>，默认 None（不获取）
    // 当主动初始化为 Some("") 或 Some("自定义值") 时，才会从响应中提取 Cookie
    // let mut need_cookie_ctx = HttpContext {
    //     cookies: Some(String::new()), // 初始化为 Some(...)（即使是空字符串），表示需要获取
    //     ..Default::default()
    // };
    pub cookies: Option<String>,
}

/// 增强版 HTTP 客户端
pub struct HttpAppClient {
    client: Client,
}

impl HttpAppClient {
    /// 创建带超时的客户端（不带拦截器）
    pub fn new(timeout_secs: u64) -> Result<Self, reqwest::Error> {
        Ok(Self {
            client: Client::builder()
                .timeout(Duration::from_secs(timeout_secs))
                .build()?,
        })
    }

    /// 创建带代理的客户端（可选是否带拦截器）
    pub fn proxy(
        timeout_secs: u64,
        proxy_url: &str,
        proxy_user: Option<&str>,
        proxy_pass: Option<&str>,
    ) -> Result<Self, reqwest::Error> {
        let mut proxy = Proxy::all(proxy_url)?;

        if let (Some(user), Some(pass)) = (proxy_user, proxy_pass) {
            proxy = proxy.basic_auth(user, pass);
        }

        Ok(Self {
            client: Client::builder()
                .timeout(Duration::from_secs(timeout_secs))
                .proxy(proxy)
                .build()?,
        })
    }

    /// 添加自定义头到请求
    fn apply_headers(
        &self,
        request_builder: RequestBuilder,
        context: &HttpAppContext,
    ) -> RequestBuilder {
        let mut builder = request_builder;

        // 添加自定义头
        for (key, value) in &context.headers {
            builder = builder.header(key, value);
        }

        builder
    }

    async fn apply_request_interceptors(
        &self,
        request_builder: RequestBuilder,
        ctx: &mut HttpAppContext,
    ) -> Result<RequestBuilder, HttpAppError> {
        let mut rb = request_builder;

        // 1. 添加认证头
        // 1. 添加认证头（失败时立即返回错误）
        if !ctx.skip_token {
            let token = get_token().await?;
            rb = rb.header("Authorization", format!("Bearer {}", token));
        }
        // 2. 添加其他通用头
        // rb = rb.header("User-Agent", "RustHttpClient/1.0");

        Ok(rb)
    }

    /// 通用请求方法
    pub async fn request<T: DeserializeOwned>(
        &self,
        method: Method,
        url: &str,
        context: Option<HttpAppContext>,
    ) -> Result<Option<T>, HttpAppError> {
        let mut ctx = context.unwrap_or_default();
        let mut request_builder = self.client.request(method.clone(), url);

        // 应用自定义头（无论是否使用拦截器）
        request_builder = self.apply_headers(request_builder, &ctx);

        // 应用请求拦截器
        request_builder = self.apply_request_interceptors(request_builder, &mut ctx).await?;

        // 发送请求
        let response = request_builder.send().await?;

        handle_response(response, Some(ctx)).await
    }

    /// GET 请求
    pub async fn get<T: DeserializeOwned>(
        &self,
        url: &str,
        context: Option<HttpAppContext>,
    ) -> Result<Option<T>, HttpAppError> {
        self.request(Method::GET, url, context.clone()).await
    }

    /// POST 请求
    pub async fn post<T: DeserializeOwned>(
        &self,
        url: &str,
        context: Option<HttpAppContext>,
    ) -> Result<Option<T>, HttpAppError> {
        self.request(Method::POST, url, context.clone()).await
    }

    /// POST JSON 请求
    pub async fn post_json<Req: Serialize + ?Sized, T: DeserializeOwned>(
        &self,
        url: &str,
        body: &Req,
        context: Option<HttpAppContext>,
    ) -> Result<Option<T>, HttpAppError> {
        let mut ctx = context.clone().unwrap_or_default();
        let mut request_builder = self.client.post(url).json(body);

        // 应用自定义头
        request_builder = self.apply_headers(request_builder, &ctx);

        // 应用请求拦截器
        request_builder = self.apply_request_interceptors(request_builder, &mut ctx).await?;

        // 发送请求
        let response = request_builder.send().await?;

        handle_response(response, context).await
    }

    /// POST Form 请求
    pub async fn post_form<T: DeserializeOwned>(
        &self,
        url: &str,
        form: &[(&str, &str)],
        context: Option<HttpAppContext>,
    ) -> Result<Option<T>, HttpAppError> {
        let mut ctx = context.clone().unwrap_or_default();
        let mut request_builder = self.client.post(url).form(form);

        // 应用自定义头
        request_builder = self.apply_headers(request_builder, &ctx);

        // 应用请求拦截器
        request_builder = self.apply_request_interceptors(request_builder, &mut ctx).await?;

        // 发送请求
        let response = request_builder.send().await?;

        handle_response(response, context).await
    }

    /// PUT JSON 请求
    pub async fn put_json<Req: Serialize + ?Sized, T: DeserializeOwned>(
        &self,
        url: &str,
        body: &Req,
        context: Option<HttpAppContext>,
    ) -> Result<Option<T>, HttpAppError> {
        let mut ctx = context.clone().unwrap_or_default();
        let mut request_builder = self.client.put(url).json(body);

        // 应用自定义头
        request_builder = self.apply_headers(request_builder, &ctx);

        // 应用请求拦截器
        request_builder = self.apply_request_interceptors(request_builder, &mut ctx).await?;

        // 发送请求
        let response = request_builder.send().await?;

        handle_response(response, context).await
    }

    /// DELETE 请求
    pub async fn delete<T: DeserializeOwned>(
        &self,
        url: &str,
        context: Option<HttpAppContext>,
    ) -> Result<Option<T>, HttpAppError> {
        self.request(Method::DELETE, url, context.clone()).await
    }

    /// PATCH JSON 请求
    pub async fn patch_json<Req: Serialize + ?Sized, T: DeserializeOwned>(
        &self,
        url: &str,
        body: &Req,
        context: Option<HttpAppContext>,
    ) -> Result<Option<T>, HttpAppError> {
        let mut ctx = context.clone().unwrap_or_default();
        let mut request_builder = self.client.patch(url).json(body);

        // 应用自定义头
        request_builder = self.apply_headers(request_builder, &ctx);

        // 应用请求拦截器
        request_builder = self.apply_request_interceptors(request_builder, &mut ctx).await?;

        // 发送请求
        let response = request_builder.send().await?;

        handle_response(response, context).await
    }

    /// 添加自定义头到上下文
    pub fn add_custom_header(
        context: &mut HttpAppContext,
        key: &str,
        value: &str,
    ) {
        context.headers.insert(key.to_string(), value.to_string());
    }

    /// 添加 Cookie 到上下文
    pub fn add_cookie(
        context: &mut HttpAppContext,
        cookie: &str,
    ) {
        context.headers.insert("Cookie".to_string(), cookie.to_string());
    }
}

/// 处理响应
async fn handle_response<T: DeserializeOwned>(response: Response, ctx: Option<HttpAppContext>) -> Result<Option<T>, HttpAppError> {
    // 如果传入了 context 且 cookies 字段为 Some，则提取响应 Cookie
    let mut updated_ctx = ctx;
    if let Some(ref mut context) = updated_ctx {
        if context.cookies.is_some() {
            let cookies_str: String = response
                .cookies()
                .map(|cookie| format!("{}={}", cookie.name(), cookie.value()))
                .collect::<Vec<_>>()
                .join("; ");

            context.cookies = Some(cookies_str);
        }
    }

    // 提取并处理认证信息（简化版）
    let _ = response.headers()
        .get("Authorization")
        .and_then(|auth_header| auth_header.to_str().ok())
        .filter(|authcode| !authcode.is_empty())
        .map(|authcode| {
            let auth_id = response.headers()
                .get("AuthorizationId")
                .and_then(|id| id.to_str().ok())
                .unwrap_or("");

            set_auth_info(authcode, auth_id, 0, true);
        });

    let status = response.status();
    let text = response.text().await?;
    if !status.is_success() {
        return Err(HttpAppError::Status(status, text));
    }

    // 尝试解析为 AjaxResult<T>，如果失败则抛出 Custom 异常
    let ajax_result: AjaxResult<T> = serde_json::from_str::<AjaxResult<T>>(&text)
        .map_err(|e| {
            // 将 JSON 解析错误转换为 Custom 异常
            HttpAppError::Custom(
                -1,
                format!("JSON 解析错误: {}\n响应内容: {}", e, text),
            )
        })?;

    if ajax_result.code == 200 {
        Ok(ajax_result.data)
    } else {
        Err(HttpAppError::Custom(ajax_result.code, ajax_result.msg))
    }
}

pub async fn test_http_client() -> Result<(), HttpAppError> {

    // 创建带拦截器的客户端
    let client = HttpAppClient::new(10)?;

    // 使用带拦截器的客户端发送请求
    let mut context = HttpAppContext::default();
    // 2. 主动初始化 cookies 字段，触发获取 Cookie
    // let mut need_cookie_ctx = HttpContext {
    //     cookies: Some(String::new()), // 初始化为 Some(...)（即使是空字符串），表示需要获取
    //     ..Default::default()
    // };
    // // 从 context 中获取响应 Cookie（字符串格式）
    // if let Some(cookies_str) = &need_cookie_ctx.cookies {
    //     println!("获取到的 Cookie: {}", cookies_str);
    //     // 输出示例：session_id=abc123; user_token=xyz789
    // }

    // 添加自定义头
    HttpAppClient::add_custom_header(&mut context, "X-Custom-Header", "value");

    // 添加完整 Cookie 字符串
    HttpAppClient::add_cookie(&mut context, "session_id=abc123; user_token=xyz789");

    // 使用 get_response 获取完整响应对象
    match client.get::<Option<String>>("https://api.example.com/data", Some(context)).await {
        Ok(response) => {
            println!("Response: {:?}", response);
        }
        Err(e) => match e {
            HttpAppError::Reqwest(err) => eprintln!("Request error: {}", err),
            HttpAppError::Status(code, msg) => eprintln!("Status error: {} - {}", code, msg),
            HttpAppError::Custom(code, msg) => eprintln!("Custom error: {} {}", code, msg)
        },
    }

    Ok(())
}